﻿#include"stdafx.h"
#ifdef LK_REFLECTION_
namespace LK
{
	namespace Reflection
	{
		PTypeNode::PTypeNode(PType id, PString const& name, PDomainNode const&baseNode, WeakPtr<PTypeLibrary> const& library)
			:PDomainNode()
		{
			if (!library.IsNull()){//先查找类库中是否有这个类型
				PTypeNode n = library.GetTypeNodeByInfo(id);
				if (n.IsNull())SetTo(new TypeNode(id, name, baseNode, library));
				else//如果有相同类型，则进行内容覆盖
				{
					*this = n;
					if (!baseNode.IsNull())SetBaseNode(baseNode);
					if (!library.IsNull())SetLibrary(library);
					if (!name.IsNullOrEmpty())SetName(name);
				}
			}
			else SetTo(new TypeNode(id, name, baseNode, library));
		}
		Collection::PArray<PTypeNode> PTypeNode::GetBaseTypeNodes() const{ return Ptr()->BaseTypeNodes; }
		void PTypeNode::AddFunction(PString const&name, Functional::PFunObjs const&fun)const { AddFunction(name, fun, Convert<PDomainNode, PObject>::RefFrom(PObject())); }
		void PTypeNode::AddFunction(PString const&name, Functional::PFunObjs const&fun, PDomainNode domain)const
		{
			Ptr()->AddFunction(name, fun,domain);
		}
		void PTypeNode::AddBaseType(PType const & node) const{ Ptr()->AddBaseType(node); }
		bool PTypeNode::IsDerivedFrom(PTypeNode n)const{ return Ptr()->IsDerivedFrom(n); }
		bool PTypeNode::CanConvertTo(PType t, bool isExplicit)const { return Ptr()->CanConvertTo(t, isExplicit); }
		bool PTypeNode::CanConstructFrom(Collection::PArray<PType>const&args, bool isExplicit )const { return Ptr()->CanConstructFrom(args, isExplicit); }
		PObject PTypeNode::DynamicConvertTo(PType dest, PObject const&source, bool isExplicit )const { return Ptr()->DynamicConvertTo(dest,source, isExplicit); }
		PObject PTypeNode::DynamicConstructFrom(Collection::PArray<PObject>const&source, bool isExplicit )const { return Ptr()->DynamicConstructFrom(source, isExplicit); }
		PLibraryNode PTypeNode::FindNodeByNameInClass(PString const&name)const{ return Ptr()->FindNodeByNameInClass(name); }
		size_t & PTypeNode::GetSizeRef() const
		{
			return Ptr()->Size;
		}
		index_t PTypeNode::CompareId(PTypeNode const & t, index_t id)
		{
			return t.IsNull()?-1:(t.GetType().GetID() - id);
		}
		void PTypeNode::AddOperatorFunction(const Functional::PFunObjs&fun) { Ptr()->AddOperatorFunction(fun); }
		void PTypeNode::AddConstructFunction(const Functional::PFunObjs&fun) { Ptr()->AddConstructFunction(fun); }
		PFunctionNode PTypeNode::GetOperatorFunctions()const { return Ptr()->GetOperatorFunctions(); }
		PFunctionNode PTypeNode::GetConstructFunctions()const { return Ptr()->GetConstructFunctions(); }
		void PTypeNode::RemoveDerivedNode(PTypeNode const&node)const{Ptr()->RemoveDerivedNode(node);}

		TypeNode::TypeNode(PType id, PString const& name, PDomainNode const&baseNode, WeakPtr<PTypeLibrary> const& library)
			:DomainNode(library, baseNode, name), Size(0) , Id(id){
			if (id.IsNull())throw PInvalidArgumentException(L"类型ID不得为NULL");
		}
		void TypeNode::Clear()
		{
			if (!DerivedTypeNodes.IsNull())
			{
				for (index_t i = 0; i < DerivedTypeNodes.GetLength(); ++i)
					DerivedTypeNodes[i].Clear();
				DerivedTypeNodes.SetToNull();
			}
			if (!BaseTypeNodes.IsNull())
			{
				PTypeNode*p = BaseTypeNodes;
				index_t len = BaseTypeNodes.size();
				for (index_t i = 0; i < len; ++i)if (!p[i].IsNull())p[i].RemoveDerivedNode(this);
				BaseTypeNodes.SetToNull();
			}
			if (!OperatorFunctions.IsNull())OperatorFunctions.Clear();
			if (!ConstructFunctions.IsNull())ConstructFunctions.Clear();
			DomainNode::Clear();
		}

		void TypeNode::AddBaseType(PType const & tp)
		{
			PTypeNode node = GetLibrary().GetTypeNodeByInfo(tp);
			if (PObject::ReferenceEqual(node, this))throw PInvalidArgumentException(L"一个类不能是自己的基类");
			if (PObject::ReferenceEqual(node, GetBaseNode()))return;
			if (BaseTypeNodes.IsNull())BaseTypeNodes = new Collection::DefaultArray<PTypeNode>();
			index_t idx = BaseTypeNodes.IndexOf(node);
			if (idx < 0)return;//已经存在该基类
			//加入基类
			BaseTypeNodes.Append(node);
			//为该类型和派生类型添加基类的方法
			Collection::PArray<PLibraryNode>& rarr = node.GetInnerNodesRef();
			if (!rarr.IsNull()){
				index_t len = rarr.size();
				PLibraryNode* p = rarr;
				for (idx = 0; idx < len; ++idx){
					PFunctionNode f = rarr[idx].CastTo<PFunctionNode>();
					if (!f.IsNull()) {
						Collection::PArray<Functional::PFunObjs> fs = f->Methods;
						PString name = f->GetName();
						if (!fs.IsNull()){
							for (index_t i = 0; i < fs.size();++i)
								AddFunction(name, fs[i],node);
						}
					}
				}
			}
			//在基类的派生类列表中添加该类
			if (node.GetPtr()->DerivedTypeNodes.IsNull())node.GetPtr()->DerivedTypeNodes = new LK::Collection::DefaultArray<PTypeNode>(1, this);
			else{
				index_t i = node.GetPtr()->DerivedTypeNodes.DichotomyIndexOf(this, &PLibraryNode::Compare);
				if (i < 0)node.GetPtr()->DerivedTypeNodes.DichotomyInsertAsc(this, &PLibraryNode::Compare);
				else node.GetPtr()->DerivedTypeNodes[i] = this;
			}
		}
		bool TypeNode::IsDerivedFrom(PTypeNode n)const
		{
			if (PObject::ReferenceEqual(this, n))return true; //认为跟本身进行派生判断为true
			if (BaseTypeNodes.IsNull() || n.IsNull())return false;
			for (index_t i = 0; i < BaseTypeNodes.size(); ++i)
				if (PObject::ReferenceEqual(BaseTypeNodes[i], n) || BaseTypeNodes[i].IsDerivedFrom(n))return true;
			return false;
		}
		void TypeNode::SetLibrary(WeakPtr<PTypeLibrary> const&lib)
		{
			if (PObject::ReferenceEqual(lib, GetLibrary()))return;
			if (!GetLibrary().IsNull())GetLibrary().SetTypeNodeByInfo(Id, PTypeNode());
			LibraryNode::SetLibrary(lib);
			if (!lib.IsNull())lib.SetTypeNodeByInfo(Id, this);
		}
		void TypeNode::AddFunction(PString const&name, Functional::PFunObjs fun) { AddFunction(name, fun,Convert<PDomainNode, PObject>::RefFrom(PObject())); }
		void TypeNode::AddFunction(PString const&name, Functional::PFunObjs fun, PDomainNode domain)
		{
			if (name.IsNullOrEmpty() || fun.IsNull())throw PInvalidArgumentException(L"传入的函数名或函数为空");
			PLibraryNode node= GetInnerNodeByName(name);
			if (node.IsNull())node=AddInnerNode(new FunctionNode(name));
			else if (node.CastTo<PFunctionNode>().IsNull())throw PReflectionException(L"类中已存在同名成员");
			void*p; fun.GetInnerPtr(&p);
			if (p){
				throw PReflectionException(L"所指定的成员函数的对象指针非空");
            }
			if (((PFunctionNode&)node).AddFunction(fun, domain) && !DerivedTypeNodes.IsNull())
				for (index_t i = 0; i < DerivedTypeNodes.size(); ++i)DerivedTypeNodes[i].AddFunction(name, fun, domain);
		}
		PLibraryNode TypeNode::FindNodeByNameInClass(PString const&name)const
		{
			PLibraryNode node = GetInnerNodeByName(name);
			if (!node.IsNull() || BaseTypeNodes.IsNull())return node;
			for (index_t i = 0; i < BaseTypeNodes.size();++i)
				if(!(node = BaseTypeNodes[i].FindNodeByNameInClass(name)).IsNull())break;
			return node;
		}
		void TypeNode::RemoveDerivedNode(PTypeNode const&node)
		{//TODO 移除派生关系时，派生类中有可能残留该类型方法
			if (DerivedTypeNodes.IsNull() || node.IsNull())return;
			index_t i = DerivedTypeNodes.DichotomyIndexOf<PTypeNode const&>(node, &PLibraryNode::Compare);
			if (i < 0)return;
			DerivedTypeNodes.RemoveAt(i);
		}

		bool TypeNode::CanConvertTo(PType t, bool isExp)const
		{
			if (t.IsNull())return false;
			PTypeNode node = (TypeNode*)this;
			if (node.GetPtr()->Id.CompareWithoutExtents(t) == 0)return true;
			if (!node.GetPtr()->GetOperatorFunctions().IsNull()) {
				Collection::PArray<Functional::PFunObjs>arr = node.GetPtr()->GetOperatorFunctions().GetPtr()->Methods;
				index_t i = arr.DichotomyIndexOf(t, &FunctionNode::OperatorCompare);
				if (i >= 0)return true;
			}
			//当isExp为false时进行模糊查询
			if (!isExp)
			{
				if (!node.GetPtr()->GetOperatorFunctions().IsNull()) {
					Collection::PArray<Functional::PFunObjs>arr = node.GetPtr()->GetOperatorFunctions().GetPtr()->Methods;
					for (index_t i = 0; i < arr.size(); ++i)
						if (t.CanDynamicConvertFrom(arr[i].GetArgsType()[0], 1))return true;
				}
			}
			return false;
		}
		bool TypeNode::CanConstructFrom(Collection::PArray<PType>const& t,bool isExp)const
		{
			if (!GetConstructFunctions().IsNull()) {
				return !GetConstructFunctions().GetFunction(t,isExp).IsNull();
			}
			return false;
		}
		PObject TypeNode::DynamicConvertTo(PType t, PObject const&source,bool isExp)const
		{
			if (t.IsNull())throw PInvalidArgumentException(L"指定的目标类型为空");
			PTypeNode node = (TypeNode*)this;
			if (node.GetPtr()->Id.CompareWithoutExtents(t) == 0)return t.SameTypeReferenceConvert(node.GetPtr()->Id,source);
			if (!node.GetPtr()->GetOperatorFunctions().IsNull()) {
				Collection::PArray<Functional::PFunObjs>arr = node.GetPtr()->GetOperatorFunctions().GetPtr()->Methods;
				index_t i = arr.DichotomyIndexOf(t, &FunctionNode::OperatorCompare);
				if (i >= 0)
				{
					Collection::PArray<PType> tarr;
					bool bf = false;
				ReFind:;
					tarr = arr[i].GetArgsType();
					if (i > 0 && tarr[0] > t) { i--; bf = true; if (tarr[0].CompareWithoutExtents(t) == 0)goto ReFind; }
					else if (i < arr.size() && tarr[0] < t) { i++; if (!bf&&tarr[0].CompareWithoutExtents(t) == 0)goto ReFind; }
					Collection::ReferenceArray<PObject> arg(1, &source);
					return arr[i].Call(source, &arg);
				}
			}
			if (!isExp)
			{
				if (!node.GetPtr()->GetOperatorFunctions().IsNull()) {
					Collection::PArray<Functional::PFunObjs>arr = node.GetPtr()->GetOperatorFunctions().GetPtr()->Methods;
					for (index_t i = 0; i < arr.size(); ++i)
						if (t.CanDynamicConvertFrom(arr[i].GetArgsType()[0], 1))
						{
							Collection::FixedArray<PObject, sizeof(size_t)> arg(1, &source);
							return arr[i].Call(PObject(), &arg);
						}
				}
			}
			throw PTypesConvertErrorException(L"无法进行从类型 "+Id.GetFullName()+L" 到类型 "+t.GetFullName()+L"的转换，缺少相应的转换函数");
		}
		PObject TypeNode::DynamicConstructFrom(Collection::PArray<PObject>const&source,bool isExp)const{
			Collection::PArray<PType>tarr;
			if (!source.IsNull())
			{
				tarr = new LK::Collection::DefaultArray<PType>(source.GetLength());
				for (index_t i = 0; i < tarr.size(); ++i)
				{
					tarr[i] = source[i].GetType();
					if (tarr[i] == PType::Make<PMObjects>())
						tarr[i] = ((PMObjects&)source[i]).GetInnerType();
				}
			}
			Functional::PFunObjs f;
			if (!GetConstructFunctions().IsNull()) {
				f = GetConstructFunctions().GetFunction(tarr, isExp);
			}
			if (f.IsNull())
			{
				PString str = L"(";
				for (index_t i = 0; i < tarr.size(); ++i)
				{
					str += tarr[i].GetFullName();
					if (i != tarr.size() - 1)str += L",";
				}
				str += L")";
				throw PTypesConvertErrorException(L"无法从类型列表 " +str+ L" 构造类型 " + Id.GetFullName());
			}
			return f.Call(PObject(), source);
		}
		void TypeNode::AddOperatorFunction(const Functional::PFunObjs&fun)
		{
			Collection::PArray<PType> tarr = fun.GetArgsType();
			//动态类型检查
			if (tarr.size() != 3 || !tarr[2].CanDynamicConvertFrom(Id) || tarr[0]==PType::Make<void>())throw PReflectionException(L"类型转换函数必须可以动态传入被转换类型，返回目标类型");
			if (OperatorFunctions.IsNull())OperatorFunctions = new FunctionNode(GetName(), GetLibrary(), this);
			else{//如果已经有目标类型一样的转换函数，则会被跳过
				for (index_t i = 0; i < OperatorFunctions->Methods.size(); ++i)
					if (OperatorFunctions->Methods[i].GetArgsType()[0] == tarr[0])return;
			}
			if (OperatorFunctions.AddOperatorFunction(fun))//如果是第一次添加
			{
				//为目标类型添加构造函数
				PType t = tarr[0];
				if (t.IsPureTypeIgnoreExtents())
				{
					PTypeNode n = GetLibrary().GetTypeNodeByInfo(t.GetID());
					if (!n.IsNull())n.AddConstructFunction(fun);
				}
			}
			//为派生类添加转换方法
			if (!DerivedTypeNodes.IsNull())
			{
				for (index_t i = 0; i < DerivedTypeNodes.size(); ++i)
					DerivedTypeNodes[i].AddOperatorFunction(fun);
			}
		}
		void TypeNode::AddConstructFunction(const Functional::PFunObjs&fun)
		{
			Collection::PArray<PType> tarr = fun.GetArgsType();
			//动态类型检查
			if (!Id.CanDynamicConvertFrom( tarr[0] ))throw PReflectionException(L"构造函数的返回值类型必须可以动态转换到该类型");
			if (ConstructFunctions.IsNull())ConstructFunctions = new FunctionNode(GetName(), GetLibrary(), this);
			if (ConstructFunctions.AddFunction(fun)&& tarr.size()==3)//如果是第一次添加且参数符合
			{
				//为参数类型添加转换函数
				PType t = tarr[2];
				if (t.IsPureTypeIgnoreExtents())
				{
					PTypeNode n = GetLibrary().GetTypeNodeByInfo(t.GetID());
					if (!n.IsNull())n.AddOperatorFunction(fun);
				}
			}
		}

	}
}
#endif
